<template>
  <div class="comp__form">
    <el-form
      ref="refForm"
      :model="form"
      :rules="rules"
      :show-message="false"
      autocomplete="off"
    >
      <el-form-item v-if="label.includes('phone')" prop="phone">
        <el-input
          v-model="form.phone"
          placeholder="请输入您的手机号码"
          :disabled="disbaleLabel.includes('phone')"
          maxlength="11"
          size="large"
        />
      </el-form-item>
      <el-form-item v-if="label.includes('code')" prop="code">
        <el-input
          v-model="form.code"
          placeholder="验证码"
          size="large"
          maxlength="6"
        >
          <template #suffix>
            <span
              v-if="countdownTime <= 0"
              class="send-code"
              :class="{ 'is-disabled': isDisableSendBtn }"
              @click.stop="handleSendCode()"
              >发送</span
            >
            <span v-else class="send-code is-disabled"
              >{{ countdownTime }}s</span
            >
          </template>
        </el-input>

        <el-dialog v-model="imgCaptchaVisible"
          align-center
          :close-on-click-modal="false"
          append-to-body
          class="img-captcha-dialog"
          width="372px">
          <p class="title">图形验证码</p>
          <el-form ref="imgCaptchaFormRef"
            :model="imgCaptchaForm"
            onsubmit="return false"
            :rules="imgCaptchaRules">
            <div class="img-wrap">
              <div class="img-box"
                v-if="!imgCaptchaURL || imgCaptchaLoading">
                <div class="el-image__error">{{imgCaptchaLoading?'加载中':'加载失败'}}</div>
              </div>

              <el-image :src="imgCaptchaURL"
                class="img-box"
                v-else></el-image>
              <div class="img-text">看不清?<el-button type="text"
                  @click="imgCaptchaRefresh">换一张</el-button>
              </div>
            </div>
            <el-form-item prop="code"
              style="margin-bottom:0;">
              <el-input v-model="imgCaptchaForm.code"
                placeholder="输入上方图形验证码"
                maxlength="4"
                size="large"
                @keydown.enter="imgCaptchaComplete"></el-input>
            </el-form-item>
          </el-form>

          <template #footer>
            <div class="dialog-footer">
              <el-button color="#eeeef2" :dark="false"
                @click="imgCaptchaVisible = false"
                size="large">取 消</el-button>
              <el-button type="primary"
                @click="imgCaptchaComplete"
                size="large">确 定</el-button>
            </div>
          </template>
        </el-dialog>

      </el-form-item>
      <el-form-item v-if="label.includes('pwd')" prop="pwd">
        <el-input
          v-model="form.pwd"
          :type="isShowPwd ? 'text' : 'password'"
          :placeholder="
            strongPassword ? '请输入8-16位数字+字母的密码组合' : '请输入密码'
          "
          size="large"
          autocomplete="off"
        >
          <template #suffix>
            <svg-icon
              :icon-class="isShowPwd ? 'eye-open' : 'eye'"
              class="fs-18 cursor"
              @click.stop="isShowPwd = !isShowPwd"
            />
          </template>
        </el-input>
      </el-form-item>
      <el-form-item v-if="label.includes('confirmPwd')" prop="confirmPwd">
        <el-input
          v-model="form.confirmPwd"
          placeholder="请再次输入密码"
          size="large"
          :type="isshowConfirmPwd ? 'text' : 'password'"
          autocomplete="off"
        >
          <template #suffix>
            <svg-icon
              :icon-class="isshowConfirmPwd ? 'eye-open' : 'eye'"
              class="fs-18 cursor"
              @click.stop="isshowConfirmPwd = !isshowConfirmPwd"
            />
          </template>
        </el-input>
      </el-form-item>
      <el-form-item v-if="label.includes('protocol')" prop="protocol">
        <el-checkbox
          v-model="form.protocol"
          class="checkbox__text"
          label="1"
          true-value="1"
        >
          <div class="checkbox__text_inner">
            <span
              >已阅读并同意<a
                href="javascript:void(0)"
                @click="invokeAPi('fq_open_url', appCfg.userProtocol)"
                class="link-btn"
                >《用户协议》</a
              ></span
            >
          </div>
        </el-checkbox>
      </el-form-item>
    </el-form>
  </div>
</template>

<script lang="ts" setup>
import { reactive, ref, watch, computed, nextTick } from "vue";
import PsMessage from "@/components/message/index";
import type { FormInstance, FormRules } from "element-plus";
import { sendSms, getCodeImg } from "@/api/login";
import { onMounted } from "vue";
import { storeToRefs, acceptHMRUpdate } from 'pinia';
import { systemAppStore } from "@/stores/system";
import { invokeAPi } from "@/xz-fn";
const _systemAppStore_ = systemAppStore();
const { appCfg } = storeToRefs(_systemAppStore_);
const form = reactive({
  phone: "",
  code: "",
  pwd: "",
  confirmPwd: "",
  protocol: false
});

export interface Props {
  label: (keyof typeof form)[];
  disbaleLabel?: (keyof typeof form)[];
  defaultValue?: Partial<Record<keyof typeof form, any>>;
  strongPassword?: boolean;
}
export interface API {
  validate: () => Promise<null | typeof form>;
}
const props = withDefaults(defineProps<Props>(), {
  label: () => [],
  disbaleLabel: () => [],
  defaultValue: () => ({}) as any,
  strongPassword: false
});

const refForm = ref<FormInstance>();
const countdownTime = ref(0);
const isShowPwd = ref(false);
const isshowConfirmPwd = ref(false);

// 图形验证码
const imgCaptchaVisible = ref(false);
const imgCaptchaForm = ref({
  code: ''
});
const imgCaptchaRules = ref({
  code: [
    { require: true, message: '请输入图形验证码', trigger: ['change'] }
  ]
});
const imgCaptchaFormRef = ref<FormInstance|null>(null);
const imgCaptchaURL = ref("");
const imgCaptchaID = ref("");
const imgCaptchaLoading = ref(false);

const isDisableSendBtn = computed(() => {
  return countdownTime.value > 0 || !/^1[3-9]\d{9}$/.test(form.phone);
});

let countdownTimer: number | null = null;

const startCountdown = (num: number = 60) => {
  countdownTime.value = num;
  if (countdownTimer) clearTimeout(countdownTimer);
  countdownTimer = window.setTimeout(() => {
    if (num > 0) {
      startCountdown(num - 1);
      return;
    }
  }, 1000);
};

watch(
  () => props.defaultValue,
  () => {
    Object.assign(form, props.defaultValue);
  }
);

const handleSendCode = (hasCaptcha: boolean = false) => {
  if (isDisableSendBtn.value) {
    return
  }

  if (!form.phone) {
    PsMessage("请输入手机号码");
    return;
  }
  const params: any = {
    phoneNumber: form.phone,
    type: "phone"
  };
  if (hasCaptcha) {
    params.captcha = imgCaptchaForm.value.code
    params.captchaID = imgCaptchaID.value
  }
  sendSms(params)
    .then((res: any) => {
      if (res?.data?.Verify === false) {
        imgCaptchaRefresh();
        PsMessage('图形验证码错误，请重新输入');
        return;
      }
      imgCaptchaVisible.value = false;
      PsMessage("发送成功");
      startCountdown();
    })
    .catch((e: any) => {
      if(e?.code === 451){
        imgCaptchaRefresh();
        onShowCaptcha();
      }else if(imgCaptchaVisible.value){
        imgCaptchaRefresh();
      }
    })
};

const validatorPohone = (rule: any, value: any, callback: any) => {
  if (!value) {
    PsMessage("请输入手机号码");
    return callback(true);
  }
  if (!/^1[3-9]\d{9}$/.test(value)) {
    PsMessage("请输入正确的手机号码");
    return callback(true);
  }
  return callback();
};

const validatorCode = (rule: any, value: any, callback: any) => {
  if (!value) {
    PsMessage("请输入手机验证码");
    return callback(true);
  }
  if (!/^\d{6}$/.test(value)) {
    PsMessage("请输入正确的手机验证码");
    return callback(true);
  }
  return callback();
};
const validatorPwd = (rule: any, value: any, callback: any) => {
  if (!value) {
    PsMessage("请输入密码");
    return callback(true);
  }
  if (
    props.strongPassword &&
    !/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$/.test(value)
  ) {
    PsMessage("格式错误，请输入8-16位数字+字母的密码组合");
    return callback(true);
  }
  return callback();
};
const validatorConfirmPwd = (rule: any, value: any, callback: any) => {
  if (!value) {
    PsMessage("请输入确认密码");
    return callback(true);
  }
  if (value !== form.pwd) {
    PsMessage("两次输入的密码不一致");
    return callback(true);
  }
  return callback();
};

const validatorProtocol = (rule: any, value: any, callback: any) => {
  if (!value) {
    PsMessage("请勾选用户协议");
    return callback(true);
  }
  return callback();
};

const rules = reactive<FormRules<typeof form>>({
  phone: [{ validator: validatorPohone, trigger: "blur" }],
  code: [{ validator: validatorCode, trigger: "blur" }],
  pwd: [{ validator: validatorPwd, trigger: "blur" }],
  confirmPwd: [{ validator: validatorConfirmPwd, trigger: "blur" }],
  protocol: [{ validator: validatorProtocol, trigger: "blur" }]
});

const validate = async (): Promise<null | typeof form> => {
  const val = await refForm.value
    ?.validateField(props.label)
    .catch(() => false);
  return val ? form : null;
};

const clearValidate = async (): Promise<void> => {
  await refForm.value
    ?.clearValidate()
};
defineExpose({
  validate,
  clearValidate
});

onMounted(() => {
  Object.assign(form, props.defaultValue);
});
/** 图形验证码-显示 */
function onShowCaptcha () {
  imgCaptchaVisible.value = true
  imgCaptchaFormRef.value?.resetFields()
}
/** 图形验证码-刷新 */
function imgCaptchaRefresh(){
  imgCaptchaLoading.value = true
  imgCaptchaURL.value = ''
  getCodeImg()
    .then((res: any) => {
      const data = res.data || {}
      nextTick(() => {
        imgCaptchaURL.value = data.captcha
      })
      imgCaptchaID.value = data.id
    })
    .finally(() => {
      imgCaptchaLoading.value = false
    })
}
/** 图形验证码-点击确认 */
function imgCaptchaComplete () {
  if (!imgCaptchaForm.value.code) {
    PsMessage('请输入图形验证码')
  } else if (/^\w{4}$/.test(imgCaptchaForm.value.code)) {
    handleSendCode(true)
  } else {
    PsMessage('图形验证码错误，请重新输入')
  }
}
</script>

<style lang="scss" scoped>
.send-code {
  // position: absolute;
  color: var(--el-color-primary);
  right: 10px;
  font-size: 14px;
  cursor: pointer;
  &.is-disabled {
    color: var(--el-text-color-disabled);
  }
}
:deep(.el-form-item) {
  margin-bottom: 10px;
}
:deep(.el-checkbox__inner::after) {
  top: 0;
}
:deep(.link-btn){
  --text-color: inherit;
}
</style>
<style lang="scss">
.img-captcha-dialog {
  .el-dialog__body {
    padding: 0 50px;
  }
  .el-dialog__footer{
    padding: 15px 0 30px;
  }
  .title {
    font-size: 14px;
    font-weight: bold;
    text-align: center;
    margin-bottom: 20px;
  }
  .img {
    &-wrap {
      display: flex;
      justify-content: space-between;
      align-items: flex-end;
      margin-bottom: 15px;
    }
    &-box {
      width: 164px;
      height: 80px;
    }
    &-text {
      display: flex;
      align-items: center;
      .el-button {
        padding: 0;
        height: auto;
      }
    }
  }
  .el-input{
    --el-component-size-large: 38px;
  }
  .dialog-footer {
    text-align: center;
    .el-button {
      width: 100px;
      --el-button-size: 38px;
      + .el-button{
        margin-left: 16px;
      }
    }
  }
}
</style>
